/***************************************************************************
 * This program is free software; you can redistribute it and/or           *
 * modify it under the terms of the GNU General Public License             *
 * as published by the Free Software Foundation; either version 2          *
 * of the License, or (at your option) any later version.                  *
 *                                                                         *
 * This program is distributed in the hope that it will be useful,         *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 * GNU General Public License for more details.                            *
 *                                                                         *
 * You should have received a copy of the GNU General Public License       *
 * along with this program; if not, write to the Free Software Foundation, *
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.         *
 *                                                                         *
 *   Copyright (C) 2007,2008 by Ivan Vucica                                *
 *   ivucica@gmail.com                                                     *
 ***************************************************************************/


#ifndef __LOGOSOURCE_H
#define __LOGOSOURCE_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <vector>
#include "token.h"
typedef std::string::size_type strpos_t;
typedef std::vector<Token>::iterator tokeniterator_t;
typedef std::vector<Token>::const_iterator consttokeniterator_t;


class LogoSource {
    public:
		LogoSource (const std::vector<Token>& proctokens) {
			sourcetokens = proctokens;
		}

        LogoSource(const char *source) {
            *this = std::string(source);
        }
        LogoSource(const std::string &source) {
            *this = source;

        }
        ~LogoSource() {}

        const LogoSource& operator= (const char* inputsource) {
            return *this = std::string(inputsource);
        }
        const LogoSource& operator= (const std::string& inputsource) {
            source = inputsource;
            Token t;
            pos = 0;

            while ((t = GetNextToken()).type!=Token::TT_EOF) {
                sourcetokens.insert(sourcetokens.end(), t);
            }
            sourcetokens.insert(sourcetokens.end(), Token::TT_EOF);
            //printf("\n");
            return *this;
        }
        Token GetNextToken() {
            if (!SkipSpaces()) return Token(Token::TT_EOF);

            std::string symbol = CollectSymbol();

            if (symbol.size())
            	return Token(symbol);
            else
                return Token(Token::TT_EOF);
        }
        bool SkipSpaces() {
            for (;pos < source.size() && source[pos]!='\n' && isspace(source[pos]);pos++);

            if (pos >= source.size()) {
                return false;
            }
            return true;
        }
        std::string CollectSymbol() {
            std::string symbol;
            char c;

			if (source[pos]=='\n') {
				pos++;
				return "\n";
			}
			bool first=true;
			while ((c = GetSymbolChar())) {

				if (c=='+' || c=='-' || c=='*' || c=='/' || c=='=') {
					if (!first)
						pos--;
					else
						symbol = c;
					return symbol;

				}
				symbol += c;
				first = false;
				if (strchr("([", c)) {
					int parentheses = 1;
					while (parentheses) {
							if (pos == source.size()) return symbol;
						if (source[pos]==c) parentheses++;
						if (c=='(')
							if (source[pos]==')') {
								parentheses--;
							} else {}
						else
							if (source[pos]==']') {
								parentheses--;
							}
						symbol += source[pos++];

					}
					return symbol;
				}
			}
			return symbol;
        }
        char GetSymbolChar() {
            if (strchr(")]", source[pos])) {
                pos++;
                return 0;
			}
			if (isspace(source[pos])) {
				return 0;
			}
            if (source[pos] == '\\') {
                char t = source[++pos];
                pos++;
                return t;
            }
            return source[pos++];
        }
        void Dump () const {
            for (consttokeniterator_t it = sourcetokens.begin(); it != sourcetokens.end(); it++) {
                it->Dump();
                putchar('\n');
            }
        }
        Token GetFirstToken() const {
        	return *sourcetokens.begin();
        }
    protected:
        std::string source;

        std::vector<Token> sourcetokens;
        strpos_t pos;
	friend class LogoInterpreter;


};

#endif
